package com.youngjun.common.jpa.web;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.youngjun.common.oss.expection.CommonException;
import com.youngjun.common.util.JsonUtils;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.time.Instant;

/**
 * @author YoungJun
 */
public class Response {

    /**
     * timestamp
     */
    private long timestamp;
    /**
     * business error code
     */
    private int code = 1;
    /**
     * exception class name
     */
    private String exception;
    /**
     * exception message
     */
    private String msg;
    /**
     * request path
     */
    private String path;
    /**
     * response data
     */
    private Object data;

    private Response() {
    }

    public static Response create() {
        Response r = new Response();
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        r.timestamp = Instant.now().toEpochMilli();
        r.path = request.getServletPath();
        return r;
    }

    public Response data(Object data) {
        this.data = data;
        return this;
    }

    public Response exception(Exception exception) {
        exception.printStackTrace();
        if (exception instanceof CommonException) {
            this.code = ((CommonException) exception).getExceptionType().getCode();
            this.msg = exception.getMessage();
        } else if (exception instanceof MethodArgumentNotValidException) {
            this.code = -1;
            this.msg = ((MethodArgumentNotValidException) exception).getBindingResult()
                    .getAllErrors()
                    .stream()
                    .map(objectError -> {
                        FieldError fieldError = (FieldError) objectError;
                        return fieldError.getDefaultMessage();
                    })
                    .reduce((result, item) -> {
                        if (result.length() > 0) {
                            result += ", ";
                        }
                        result += item;
                        return result;
                    }).get();
        } else {
            this.code = -1;
            this.msg = exception.getMessage();
        }
        this.exception = exception.getClass().getName();
        return this;
    }

    public long getTimestamp() {
        return timestamp;
    }

    public int getCode() {
        return code;
    }

    public String getException() {
        return exception;
    }

    public String getMsg() {
        return msg;
    }

    public String getPath() {
        return path;
    }

    public Object getData() {
        return data;
    }

    @Override
    public String toString() {
        try {
            return JsonUtils.getObjectMapper().writeValueAsString(this);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
}